#include <head.h>

/*
struct stat{
    dev_t     st_dev;      设备 ID 
    ino_t     st_ino;      inode 编号 
    mode_t    st_mode;     文件类型和权限 
    nlink_t   st_nlink;    硬链接数量 
    uid_t     st_uid;      文件所有者的用户 ID 
    gid_t     st_gid;      文件所有者的组 ID 
    dev_t     st_rdev;     设备 ID（如果是设备文件） 
    off_t     st_size;     文件大小（以字节为单位） 
    blkcnt_t  st_blocks;   文件占用的块数 
    time_t    st_atime;    最近访问时间 
    time_t    st_mtime;    最近修改时间 
    time_t    st_ctime;    状态改变时间 
    };

struct passwd {
    char   *pw_name;    /* 用户名 
    char   *pw_passwd;  /* 密码（通常为空或无用） 
    uid_t   pw_uid;     /* 用户 ID 
    gid_t   pw_gid;     /* 组 ID 
    char   *pw_gecos;   /* 用户描述信息 
    char   *pw_dir;     /* 用户的主目录 
    char   *pw_shell;   /* 用户的默认 shell 
    };

struct group {
    char   *gr_name;    组名 
    char   *gr_passwd;  密码（通常为空或无用） 
    gid_t   gr_gid;     组 ID 
    char  **gr_mem;     组成员列表 
    };
*/
void my_ls(char *file_name)
{
    struct stat file_stat;
    struct passwd *u_name;
    struct group *g_name;
    stat(file_name, &file_stat);

    //***********************************判定文件类型*************************************
    switch(file_stat.st_mode & __S_IFMT)//S_IFMT 是一个掩码，用来提取文件类型位。
    {
        case __S_IFREG://常规文件
            printf("-");
            break;
        case __S_IFDIR://目录
            printf("d");
            break;
        case __S_IFCHR://字符设备
            printf("c");
            break;
        case __S_IFBLK://块设备
            printf("b");
            break;
        case __S_IFIFO://FIFO(管道)
            printf("p");
            break;
        case __S_IFSOCK://套接字
            printf("s");
            break;
        case __S_IFLNK://符号链接
            printf("l");
            break;
        default:
            printf(" ");
            break;
    }

    //***********************************判定文件权限*************************************
    printf((file_stat.st_mode & S_IRUSR) ? "r" : "-");
    printf((file_stat.st_mode & S_IWUSR) ? "w" : "-");
    printf((file_stat.st_mode & S_IXUSR) ? "x" : "-");
    printf((file_stat.st_mode & S_IRGRP) ? "r" : "-");
    printf((file_stat.st_mode & S_IWGRP) ? "w" : "-");
    printf((file_stat.st_mode & S_IXGRP) ? "x" : "-");
    printf((file_stat.st_mode & S_IROTH) ? "r" : "-");
    printf((file_stat.st_mode & S_IWOTH) ? "w" : "-");
    printf((file_stat.st_mode & S_IXOTH) ? "x" : "-");

    //***********************************判定文件链接*************************************
    printf(" %d",(int)file_stat.st_nlink);

    //***********************************判定文件用户*************************************
    u_name = getpwuid(file_stat.st_uid);
    printf(" %s",u_name->pw_name);

    //***********************************判定文件用户组*************************************
    g_name = getgrgid(file_stat.st_uid);
    printf(" %s",u_name->pw_name);

    //***********************************判定文件大小**************************************
    printf(" %4d",(int)file_stat.st_size);

    //***********************************判定时间-月份*************************************
    struct tm *file_tm = localtime(&file_stat.st_mtime);
    printf(" %d月",file_tm->tm_mon+1);

    //***********************************判定时间-日期************************************
    printf(" %d", file_tm->tm_mday);

    //***********************************判定时间-时 分************************************
    printf(" %d:%d", file_tm->tm_hour, file_tm->tm_min);

    //***********************************字符串操作****************************************
    int i=0;
    int j=0;

    //***********************************字符串操作：求斜杠位置******************************
    for(i=strlen(file_name)-1;i>0;i--)
    {
        if('/'==file_name[i])
        {
            break;
        }
    }
    i++;

    // *********************************字符串操作:循环写入*********************************
    for(j=0;file_name[i]!='\0';i++,j++)
    {
        file_name[j]=file_name[i];
    }
    file_name[j]='\0';

    //************************************判定文件名***************************************
    printf(" %s\n",file_name);
}

void dir_(const char *dir_name)
{
    //打开文件夹
    char file_name[128];
    DIR *__drip = opendir(dir_name);
    struct dirent *dir_str;

    while((dir_str = readdir(__drip))!=NULL)
    {
        memset(file_name,0,sizeof(file_name));
        strcpy(file_name,dir_name);
        strcat(file_name,"/");
        strcat(file_name,dir_str->d_name);

        //开始输出
        if(strcmp(dir_str->d_name,".")&&strcmp(dir_str->d_name,".."))
        {
            if(DT_DIR == dir_str->d_type)
            {
                dir_(file_name);//若检测到文件夹，就递归调用
                break;
            }
            my_ls(file_name);
        }
    }
    closedir(__drip);
    return ;
}

int main(int argc,const char *argv[])
{
    if(2==argc)
    {
        struct stat file_stat;//判定文件类型结构体

        stat(argv[1],&file_stat);

        //判定文件类型
        switch(file_stat.st_mode & S_IFMT)
        {
            case __S_IFDIR://目录文件
                dir_(argv[1]);
                break;
            default://其他文件
                my_ls((char*)argv[1]);
                break;
        }
    }
    return 0;
}